//
//  GLVideoGesActionView.swift
//  uisliderDel
//
//  Created by quan on 2019/8/13.
//  Copyright © 2019 quan. All rights reserved.
//

import UIKit
import SnapKit

/**
 *  视频播放的遮罩控制层，包含进度显示
 */
class GLVideoGesActionView: UIView {
    var backBlock: (()->Void)?
    var playBlock: (()->Void)?
    var lockBlock: (()->Void)?
    var unlockBlock: (()->Void)?
    var singleTapBlock: (()->Void)?
    var fullScreenBlock: (()->Void)?
    var toolBarAutoHideBlock: (()->Void)?
    var needAutoHideToolBar: Bool = true   // 是否需要自动隐藏
    var usingFullScreenBlock: Bool = false // 是否使用自定义的fullScreenBlock代替原先事件
    var type: GLVideoPlayerType? {
        didSet {
            self.changeSliderShowByType()
        }
    }
    
    private var slider: GLSlider!
    var topBGView = GLGradualView.init(type: .fromTopToBottom)
    var bottomBGView = GLGradualView.init(type: .fromBottomToTop)
    var titleLabel = UILabel.init()
    private var backButton = UIButton.init(type: .custom)
    private var lockButton = UIButton.init(type: .custom)
    private var playButton = UIButton.init(type: .custom)
    var fullScreenButton = UIButton.init(type: .custom)
    private var brightnessVolumeView = BrightnessVolumeView.init(frame: .zero)
    private var currentTimeLabel = UILabel.init()
    private var totalDurationLabel = UILabel.init()
    
    var isShowToolBar = true
    private var isPlaying = false
    private var isFullScreen = false
    private var isLocking = false
    
    private var isMediaSliderBeingDragged = false
    weak var delegatePlayer: IJKMediaPlayback? {
        didSet {
            self.refreshMediaControl()
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.setupViews()
        
        self.bindActions()
        
        let tapGes = UITapGestureRecognizer.init(target: self, action: #selector(tapAction(sender:)))
        self.addGestureRecognizer(tapGes)
        
        NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func updatePlayButtonUI() {
        if let player = self.delegatePlayer {
            if player.isPlaying() {
                playButton.setImage(GLVideoGesActionView.gl_image(named: "02暂停"), for: .normal)
            }
            else {
                playButton.setImage(GLVideoGesActionView.gl_image(named: "01开始"), for: .normal)
            }
        }
    }
    
    private func setupViews() {
        slider = GLSlider.init()
        let topBGHeight = UIApplication.shared.statusBarFrame.height + 44.0
        self.addSubview(topBGView)
        topBGView.snp.makeConstraints { (make) in
            make.top.left.right.equalToSuperview()
            make.height.equalTo(topBGHeight)
        }
        
        backButton.setImage(GLVideoGesActionView.gl_image(named: "back_white"), for: .normal)
        backButton.setImage(GLVideoGesActionView.gl_image(named: "back_white2"), for: .highlighted)
        topBGView.addSubview(backButton)
        backButton.snp.makeConstraints { (make) in
            make.left.equalToSuperview().offset(5)
            make.width.height.equalTo(40)
            make.centerY.equalToSuperview()
        }
        
        titleLabel.font = .systemFont(ofSize: 17, weight: .medium)
        titleLabel.textColor = .white
        titleLabel.alpha = 0.0
        topBGView.addSubview(titleLabel)
        titleLabel.snp.makeConstraints { (make) in
            make.left.equalTo(backButton.snp.right).offset(15)
            make.right.equalToSuperview().offset(-15)
            make.centerY.equalToSuperview()
        }
        
        self.addSubview(bottomBGView)
        bottomBGView.snp.makeConstraints { (make) in
            make.left.bottom.right.equalToSuperview()
            make.height.equalTo(44)
        }
        
        lockButton.setImage(GLVideoGesActionView.gl_image(named: "开锁"), for: .normal)
        self.addSubview(lockButton)
        lockButton.snp.makeConstraints { (make) in
            make.left.equalToSuperview().offset(15)
            make.centerY.equalToSuperview()
            make.width.height.equalTo(40)
        }
        
        playButton.setImage(GLVideoGesActionView.gl_image(named: "01开始"), for: .normal)
        bottomBGView.addSubview(playButton)
        playButton.snp.makeConstraints { (make) in
            make.left.equalToSuperview()
            make.width.height.equalTo(40)
            make.centerY.equalToSuperview()
        }
        
        fullScreenButton.setImage(GLVideoGesActionView.gl_image(named: "03放大"), for: .normal)
        bottomBGView.addSubview(fullScreenButton)
        fullScreenButton.snp.makeConstraints { (make) in
            make.width.height.equalTo(40)
            make.right.equalToSuperview()
            make.centerY.equalToSuperview()
        }
        
        // 显示进度的label、进度条
        currentTimeLabel.font = .systemFont(ofSize: 10.0, weight: .bold)
        currentTimeLabel.textColor = .white
        bottomBGView.addSubview(currentTimeLabel)
        currentTimeLabel.snp.makeConstraints { (make) in
            make.centerY.equalToSuperview()
            make.left.equalTo(playButton.snp.right).offset(2)
        }
        
        totalDurationLabel.font = .systemFont(ofSize: 10.0, weight: .bold)
        totalDurationLabel.textColor = .white
        bottomBGView.addSubview(totalDurationLabel)
        totalDurationLabel.snp.makeConstraints { (make) in
            make.centerY.equalToSuperview()
            make.right.equalTo(fullScreenButton.snp.left).offset(-2)
        }
        
        bottomBGView.addSubview(slider)
        slider.snp.makeConstraints { (make) in
            make.top.bottom.equalToSuperview()
            make.left.equalTo(currentTimeLabel.snp.right).offset(10)
            make.right.equalTo(totalDurationLabel.snp.left).offset(-10)
        }
        
        // 调节音量 亮度 view
        self.addSubview(brightnessVolumeView)
        brightnessVolumeView.snp.makeConstraints { (make) in
            make.left.right.equalToSuperview()
            make.top.equalTo(topBGView.snp.bottom)
            make.bottom.equalTo(bottomBGView.snp.top)
        }
        self.bringSubviewToFront(lockButton)
        self.lockButton.isHidden = true
    }
    
    private func changeSliderShowByType() {
        var shouldHideSlider = true
        if type != nil && type! == .replay {
            shouldHideSlider = false
        }
        self.playButton.isHidden = shouldHideSlider
        self.slider.isHidden = shouldHideSlider
        self.currentTimeLabel.isHidden = shouldHideSlider
        self.totalDurationLabel.isHidden = shouldHideSlider
    }
    
    private func bindActions() {
        backButton.addTarget(self, action: #selector(backAction), for: .touchUpInside)
        lockButton.addTarget(self, action: #selector(lockAction), for: .touchUpInside)
        playButton.addTarget(self, action: #selector(playAction), for: .touchUpInside)
        fullScreenButton.addTarget(self, action: #selector(fullScreenAction), for: .touchUpInside)
        
        // slider actions
        slider.addTarget(self, action: #selector(didSliderTouchCancel), for: .touchCancel)
        slider.addTarget(self, action: #selector(didSliderTouchDown), for: .touchDown)
        slider.addTarget(self, action: #selector(didSliderTouchUpInside), for: .touchUpInside)
        slider.addTarget(self, action: #selector(didSliderTouchupOutside), for: .touchUpOutside)
        slider.addTarget(self, action: #selector(didSliderValueChanged), for: .valueChanged)
    }
    
    // MARK: public actions
    func autoHideToolBar() {
        guard needAutoHideToolBar == true else {
            return
        }
        
        NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(hideToolBarIfNeeded), object: nil)
        self.perform(#selector(hideToolBarIfNeeded), with: nil, afterDelay: 2.0)
    }
    
    func manualHideToolBar() {
        NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(hideToolBarIfNeeded), object: nil)
        self.perform(#selector(hideToolBarIfNeeded), with: nil, afterDelay: 2.0)
    }
    
    func cancelManualHideToolBar() {
        NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(hideToolBarIfNeeded), object: nil)
    }
    
    @objc private func hideToolBarIfNeeded() {
        let orientation = UIApplication.shared.statusBarOrientation
        if orientation == .landscapeLeft || orientation == .landscapeRight {
            isShowToolBar = false
            self.hideToolBarAnimation()
            self.toolBarAutoHideBlock?()
        }
    }
    
    // MARK: slider actions
    @objc private func didSliderTouchCancel() {
        self.endDragMediaSlider()
    }
    
    @objc private func didSliderTouchDown() {
        self.beginDragMediaSlider()
    }
    
    @objc private func didSliderTouchUpInside() {
        if let player = self.delegatePlayer {
            player.currentPlaybackTime = TimeInterval(slider.value)
            if !player.isPlaying() {
                player.prepareToPlay()
                player.play()
            }
        }
        self.endDragMediaSlider()
    }
    
    @objc private func didSliderTouchupOutside() {
        self.endDragMediaSlider()
    }
    
    @objc private func didSliderValueChanged() {
        self.continueDragMediaSlider()
    }
    
    
    // MARK: other actions
    @objc func backAction() {
        let uiOrientation = UIApplication.shared.statusBarOrientation
        if uiOrientation == .landscapeLeft || uiOrientation == .landscapeRight {
            self.fullScreenAction()
        }
        else if uiOrientation == .portrait || uiOrientation == .portraitUpsideDown {
            self.backBlock?()
        }
    }
    
    @objc private func lockAction() {
        isLocking = !isLocking
        if isLocking {
            lockButton.setImage(GLVideoGesActionView.gl_image(named: "锁定"), for: .normal)
            
            playButton.isHidden = true
            fullScreenButton.isHidden = true
            slider.isHidden = true
            currentTimeLabel.isHidden = true
            totalDurationLabel.isHidden = true
            
            isShowToolBar = false
            brightnessVolumeView.isUserInteractionEnabled = false
            self.hideToolBarAnimation()
            self.lockBlock?()
        }
        else {
            lockButton.setImage(GLVideoGesActionView.gl_image(named: "开锁"), for: .normal)
            
            playButton.isHidden = false
            fullScreenButton.isHidden = false
            slider.isHidden = false
            currentTimeLabel.isHidden = false
            totalDurationLabel.isHidden = false
            
            isShowToolBar = true
            brightnessVolumeView.isUserInteractionEnabled = true
            self.showToolBarAnimation()
            self.unlockBlock?()
        }
    }
    
    @objc private func playAction() {
        if let player = self.delegatePlayer {
            if player.isPlaying() {
                playButton.setImage(GLVideoGesActionView.gl_image(named: "02暂停"), for: .normal)
                player.pause()
            }
            else {
                playButton.setImage(GLVideoGesActionView.gl_image(named: "01开始"), for: .normal)
                player.prepareToPlay()
                player.play()
            }
        }
    }
    
    @objc private func fullScreenAction() {
        if usingFullScreenBlock && fullScreenBlock != nil {
            self.fullScreenBlock?()
            return
        }
        
        let uiOrientation = UIApplication.shared.statusBarOrientation
        if  uiOrientation == .portrait || uiOrientation == .portraitUpsideDown {
            let value = UIInterfaceOrientation.landscapeRight.rawValue
            UIDevice.current.setValue(value, forKey: "orientation")
            isFullScreen = true
            fullScreenButton.setImage(GLVideoGesActionView.gl_image(named: "04缩小"), for: .normal)
        }
        else if uiOrientation == .landscapeRight || uiOrientation == .landscapeLeft {
            let value = UIInterfaceOrientation.portrait.rawValue
            UIDevice.current.setValue(value, forKey: "orientation")
            isFullScreen = false
            fullScreenButton.setImage(GLVideoGesActionView.gl_image(named: "03放大"), for: .normal)
        }
    }
    
    @objc private func tapAction(sender: UITapGestureRecognizer) {
        isShowToolBar = !isShowToolBar
        if isShowToolBar {
            self.showToolBarAnimation()
            self.refreshMediaControl()
            
        }
        else {
            self.hideToolBarAnimation()
        }
        singleTapBlock?()
    }
    
    @objc private func orientationChanged() {
        let uiOrientation = UIApplication.shared.statusBarOrientation
        if  uiOrientation == .portrait || uiOrientation == .portraitUpsideDown {
            isFullScreen = false
            
            if !usingFullScreenBlock || fullScreenBlock == nil {
                fullScreenButton.setImage(GLVideoGesActionView.gl_image(named: "03放大"), for: .normal)
            }
        }
        else if uiOrientation == .landscapeRight || uiOrientation == .landscapeLeft {
            isFullScreen = true
            
            if !usingFullScreenBlock || fullScreenBlock == nil {
                fullScreenButton.setImage(GLVideoGesActionView.gl_image(named: "04缩小"), for: .normal)
            }
        }
    }
    
    @objc private func showToolBarAnimation() {
        UIView.animate(withDuration: 0.25) {
            self.topBGView.alpha = 1.0
            self.bottomBGView.alpha = 1.0
            self.lockButton.alpha = 1.0
            
            let orientation = UIApplication.shared.statusBarOrientation
            if orientation == .landscapeLeft || orientation == .landscapeRight {
                self.titleLabel.alpha = 1.0
                self.autoHideToolBar()
            }
            else {
                self.titleLabel.alpha = 0.0
            }
        }
    }
    
    @objc private func hideToolBarAnimation() {
        UIView.animate(withDuration: 0.25) {
            let orientation = UIApplication.shared.statusBarOrientation
            if orientation == .landscapeLeft || orientation == .landscapeRight {
                self.topBGView.alpha = 0.0
            }
            self.bottomBGView.alpha = 0.0
            self.lockButton.alpha = 0.0
        }
    }
    
    // MARK: media controls
    private func beginDragMediaSlider() {
        isMediaSliderBeingDragged = true
    }
    
    private func endDragMediaSlider() {
        isMediaSliderBeingDragged = false
    }
    
    private func continueDragMediaSlider() {
        self.refreshMediaControl()
    }
    
    @objc private func refreshMediaControl() {
        // duration
        guard let player = self.delegatePlayer else {
            return
        }
        
        let duration = player.duration
        let intDuration = Int(duration + 0.5)
        if intDuration > 0 {
            slider.maximumValue = Float(intDuration)
            totalDurationLabel.text = String(format: "%02d:%02d", Int(intDuration / 60), Int(intDuration % 60))
        }
        else {
            slider.maximumValue = 1.0
            totalDurationLabel.text = "--:--"
        }
    
    
        // position
        let position: TimeInterval
        if isMediaSliderBeingDragged {
            position = TimeInterval(slider.value)
        }
        else {
            position = player.currentPlaybackTime;
        }
        let intPosition = Int(position + 0.5)
        if intDuration > 0 {
            slider.value = Float(intPosition)
        }
        else {
            slider.value = 0.0
        }
//        GLLog?.debug("?????  \(player.currentPlaybackTime)  / \(player.playableDuration)")
//        GLLog?.debug("当前播放时间: \(String(format:"%02d:%02d", Int((intPosition / 60)), Int((intPosition % 60))))")
        currentTimeLabel.text = String(format:"%02d:%02d", Int((intPosition / 60)), Int((intPosition % 60)))
    
    
        // status
//        let isPlaying = player.isPlaying()
        NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(refreshMediaControl), object: nil)
        
        if isShowToolBar {
            self.perform(#selector(refreshMediaControl), with: nil, afterDelay: 0.5)
        }
    }
    
    class func gl_image(named name: String) -> UIImage {
        let bundle = Bundle(path: (Bundle(for: self).resourcePath! + "/GLVideoPlayerForIJK.bundle"))
        if let image = UIImage(named: name, in: bundle, compatibleWith: nil) {
            return image
        }
        return UIImage()
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}
